package com.qingxin.sys.verifier;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.qingxin.sys.utils.StringUtils;
import com.qingxin.sys.verifier.rules.AjaxRule;
import com.qingxin.sys.verifier.rules.AnyItemRule;
import com.qingxin.sys.verifier.rules.ComboxRule;
import com.qingxin.sys.verifier.rules.CompareRule;
import com.qingxin.sys.verifier.rules.InputRule;
import com.qingxin.sys.verifier.rules.NumberRangeRule;
import com.qingxin.sys.verifier.rules.RegexRule;

/**
 * 表示一个表单项或一个字段
 * @author Administrator
 *
 */
public class FormItem extends VerifyItem {

	private String id;
	private String name;
	private String label;
	private String tips;
	private boolean empty;
	private boolean notnull;
	private boolean check;
	private String settings;
	private String expr;
	
	public FormItem() {
		this.label = "";
		this.tips = "";
		this.empty = false;
		this.notnull = true;
		this.foreground = true;
		this.background = true;
	}
	
	
	/**
	 * 验证字段有效性
	 * 
	 * @param form
	 * @param formMap
	 * @return
	 */
	@Override
	public boolean verify(Form form, FormMap formMap) {
		if(notnull && formMap.getParameter(name) == null){
			form.addMessage(new VerifyMsg(getId(), name, label, this.getClass().getSimpleName(), "值不能为null"));
			return false;
		}
		if(empty){
			String val = formMap.getParameter(name);
			if(val == null || val.length()==0){
				return true;
			}
		}
		boolean allpass = true;
		for(VerifyRule rule : rules) {
			if(!rule.isBackground()){
				continue;
			}
			boolean pass = rule.isValid(name, label, formMap);
			if(!pass){
				allpass = false;
				form.addMessage(rule.getMessage(getId(), name, label));
				break;
			}
		}
		return allpass;
	}
	
	
	/**
	 * 获取前台验证配置
	 * 
	 * @return
	 */
	@Override
	public Map<String, Object> getItemCfg(){
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("id", getId());
		if(tips != null && tips.length() > 0){
			map.put("tips", tips);
		}
		if(empty){
			map.put("empty", empty);
		}
		if(check){
			map.put("check", check);
		}
		if(settings != null){
			map.put("settings", settings);
		}
		List<Object> ruleList = new ArrayList<Object>();
		for(VerifyRule rule : rules){
			if(!rule.isForeground()){
				continue;
			}
			Object cfg = rule.getRuleCfg(name, label);
			if(cfg != null){
				ruleList.add(cfg);
			}
		}
		if(ruleList.size() == 0){
			return null;
		}
		map.put("rules", ruleList);
		return map;
	}
	
	
	public String getId() {
		if(id==null || id.length()==0){
			return name;
		}
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	@Override
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getLabel() {
		return label;
	}
	public void setLabel(String label) {
		this.label = label;
	}
	public String getTips() {
		return tips;
	}
	public void setTips(String tips) {
		this.tips = tips;
	}
	public boolean isEmpty() {
		return empty;
	}
	public void setEmpty(boolean empty) {
		this.empty = empty;
	}
	public boolean isNotnull() {
		return notnull;
	}
	public void setNotnull(boolean notnull) {
		this.notnull = notnull;
	}
	public boolean isCheck() {
		return check;
	}
	public void setCheck(boolean check) {
		this.check = check;
	}
	public String getSettings() {
		return settings;
	}
	public void setSettings(String settings) {
		this.settings = settings;
	}
	public String getExpr() {
		return expr;
	}
	public void setExpr(String expr) {
		this.expr = expr;
		if(StringUtils.isNotEmpty(expr)){
			parseRules(expr, false);
		}
	}


	public void parseRules(String rulesExpr, boolean single) {
		String[] exprArray = null;
		if(single){
			exprArray = new String[]{rulesExpr};
		}else{
			exprArray = rulesExpr.trim().split("\\s+");
		}
		for(String expr : exprArray) {
			Matcher m = null;
			if(expr.startsWith("required") && (m = Pattern.compile("^required(:(\\w+)?)?(\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				RegexRule rule = new RegexRule();
				rule.setRuleArgs(m.group(2));
				rule.setCompare("or");
				rule.setRegexp("^[\\s\\S]*[^\\s\u3000]+[\\s\\S]*$");
				String error = m.group(4);
				if(error == null){
					error = "不能为空.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if(expr.startsWith("reg") && (m = Pattern.compile("^reg(:(\\w+)?)?\\[(.+)\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				RegexRule rule = new RegexRule();
				rule.setRuleArgs(m.group(2));
				rule.setCompare("or");
				rule.setRegexp(m.group(3));
				String error = m.group(5);
				if(error == null){
					error = "输入格式错误.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if(expr.startsWith("ajax") && (m = Pattern.compile("^ajax(:(\\w+)?)?\\[(.+?)(,(.*?))?(,(.*?))?(,(.+))?\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				AjaxRule rule = new AjaxRule();
				rule.setRuleArgs(m.group(2));
				rule.setUrl(m.group(3));
				String params = m.group(5);
				String okcode = m.group(7);
				String errcode = m.group(9);
				String error = m.group(11);
				if(params != null && params.length() > 0){
					rule.setParams(params);
				}
				if(okcode != null && okcode.length() > 0){
					rule.setOkcode(okcode);
				}
				if(errcode != null &&  errcode.length() > 0){
					rule.setErrcode(errcode);
				}
				if(error != null && error.length() > 0){
					rule.setError(error);
				}
				addRule(rule);
				
			}else if((expr.startsWith("len-max") || expr.startsWith("chk-max") || expr.startsWith("select-max"))
					&& (m = Pattern.compile("^(len-max|chk-max|select-max)(:(\\w+)?)?\\[(\\d+)\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				InputRule rule = new InputRule();
				String type = m.group(1);
				rule.setRuleArgs(m.group(3));
				rule.setType("len-max".equals(type) ? "size" : "chk-max".equals(type) ? "checked" : "selected");
				rule.setMax(m.group(4));
				String error = m.group(6);
				if(error == null){
					error = "len-max".equals(type) ? "最多{max}个字符." : "最多选择{max}项.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if((expr.startsWith("len-min") || expr.startsWith("chk-min") || expr.startsWith("select-min"))
					&& (m = Pattern.compile("^(len-min|chk-min|select-min)(:(\\w+)?)?\\[(\\d+)\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				InputRule rule = new InputRule();
				String type = m.group(1);
				rule.setRuleArgs(m.group(3));
				rule.setType("len-min".equals(type) ? "size" : "chk-min".equals(type) ? "checked" : "selected");
				rule.setMin(m.group(4));
				String error = m.group(6);
				if(error == null){
					error = "len-min".equals(type) ? "最少{max}个字符." : "最少选择{max}项.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if((expr.startsWith("len-eq") || expr.startsWith("chk-eq") || expr.startsWith("select-eq"))
					&& (m = Pattern.compile("^(len-eq|chk-eq|select-eq)(:(\\w+)?)?\\[(\\d+)\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				InputRule rule = new InputRule();
				String type = m.group(1);
				rule.setRuleArgs(m.group(3));
				rule.setType("len-eq".equals(type) ? "size" : "chk-eq".equals(type) ? "checked" : "selected");
				rule.setMin(m.group(4));
				rule.setMax(m.group(4));
				String error = m.group(6);
				if(error == null){
					error = "len-eq".equals(type) ? "必须由{min}个字符组成." : "必须选择{min}项.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if((expr.startsWith("len") || expr.startsWith("chk") || expr.startsWith("select"))
					&& (m = Pattern.compile("^(len|chk|select)(:(\\w+)?)?\\[(\\d+),(\\d+)\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				InputRule rule = new InputRule();
				String type = m.group(1);
				rule.setRuleArgs(m.group(3));
				rule.setType("len".equals(type) ? "size" : "chk".equals(type) ? "checked" : "selected");
				rule.setMin(m.group(4));
				rule.setMax(m.group(5));
				String error = m.group(7);
				if(error == null){
					error = "len".equals(type) ? "必须由{min}~{max}个字符组成." : "必须选择{min}~{max}项.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if(expr.startsWith("set") && (m = Pattern.compile("^set(:(\\w+)?)?\\[(.+)\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				RegexRule rule = new RegexRule();
				rule.setRuleArgs(m.group(2));
				rule.setForeground(false);
				rule.setCompare("or");
				rule.setRegexp(m.group(3));
				String error = m.group(5);
				if(error == null){
					error = "值无效.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if(expr.startsWith("combox") && (m = Pattern.compile("^combox(:(\\w+)?)?\\[(\\w+)(,(\\w+))?\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				ComboxRule rule = new ComboxRule();
				rule.setRuleArgs(m.group(2));
				rule.setValuename(m.group(3));
				rule.setValueid(m.group(5));
				String error = m.group(7);
				if(error == null){
					error = "请选择.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if(expr.startsWith("num-fmt") && (m = Pattern.compile("^num-fmt(:(\\w+)?)?\\[(\\d+)(,(\\d+))?(,([-+]))?\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				RegexRule rule = new RegexRule();
				rule.setRuleArgs(m.group(2));
				rule.setCompare("or");
				int intlen = Integer.parseInt(m.group(3));
				int declen = 0;
				String devstr = m.group(5);
				if(devstr != null){
					declen = Integer.parseInt(devstr);
				}
				if(intlen == 0){
					intlen = 1;
				}
				String sign = m.group(7);
				StringBuilder regexp = new StringBuilder("^");
				StringBuilder deferr = new StringBuilder();
				if(!"+".equals(sign)){
					regexp.append("-?");
				}
				regexp.append("\\d{1,").append(intlen).append("}");
				deferr.append("必须是数字，整数部分最多").append(intlen).append("位");
				if(declen > 0){
					regexp.append("(\\.\\d{1,").append(declen).append("})?");
					deferr.append("，小数最多").append(declen).append("位");
				}
				regexp.append("$");
				rule.setRegexp(regexp.toString());
				String error = m.group(9);
				if(error == null){
					error = deferr.toString();
				}
				rule.setError(error);
				addRule(rule);
				
			}else if(expr.startsWith("num-max") && (m = Pattern.compile("^num-max(:(\\w+)?)?\\[(-?\\d+(\\.\\d+)?)\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				InputRule rule = new InputRule();
				rule.setRuleArgs(m.group(2));
				rule.setType("number");
				rule.setMin("-2000000000");
				rule.setMax(m.group(3));
				String error = m.group(6);
				if(error == null){
					error = "值必须小于等于{max}.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if(expr.startsWith("num-min") && (m = Pattern.compile("^num-min(:(\\w+)?)?\\[(-?\\d+(\\.\\d+)?)\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				InputRule rule = new InputRule();
				rule.setRuleArgs(m.group(2));
				rule.setType("number");
				rule.setMin(m.group(3));
				rule.setMax("2000000000");
				String error = m.group(6);
				if(error == null){
					error = "值必须大于等于{min}.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if(expr.startsWith("numrange") && (m = Pattern.compile("^numrange(:(\\w+)?)?\\[(.+)\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				NumberRangeRule rule = new NumberRangeRule();
				rule.setRuleArgs(m.group(2));
				rule.setExpr(m.group(3));
				String error = m.group(5);
				if(error == null){
					error = "值无效.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if(expr.startsWith("num") && (m = Pattern.compile("^num(:(\\w+)?)?\\[(-?\\d+(\\.\\d+)?),(-?\\d+(\\.\\d+)?)\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				InputRule rule = new InputRule();
				rule.setRuleArgs(m.group(2));
				rule.setType("number");
				rule.setMin(m.group(3));
				rule.setMax(m.group(5));
				String error = m.group(8);
				if(error == null){
					error = "值必须在{min}~{max}之间.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if(expr.startsWith("any") && (m = Pattern.compile("^any(:(\\w+)?)?\\[(.+?)(,(.*?))?(,(\\d*))?\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				AnyItemRule rule = new AnyItemRule();
				rule.setRuleArgs(m.group(2));
				rule.setDestname(m.group(3));
				rule.setDestid(m.group(5));
				String min = m.group(7);
				String error = m.group(9);
				if(min != null && min.length() > 0){
					rule.setMin(Integer.parseInt(min));
				}
				if(error != null && error.length() > 0){
					rule.setError(error);
				}
				addRule(rule);
				
			}else if(expr.startsWith("compare") && (m = Pattern.compile("^compare(:(\\w+)?)?\\[(\\w+)(,(\\w+))?\\](\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				CompareRule rule = new CompareRule();
				rule.setRuleArgs(m.group(2));
				rule.setDestname(m.group(3));
				rule.setDestid(m.group(5));
				String error = m.group(7);
				if(error == null){
					error = "输入错误.";
				}
				rule.setError(error);
				addRule(rule);
				
			}else if(expr.startsWith("notempty") && (m = Pattern.compile("^notempty(:(\\w+)?)?(\\{(.+)\\})?$").matcher(expr)) != null && m.find()){
				InputRule rule = new InputRule();
				rule.setRuleArgs(m.group(2));
				rule.setType("size");
				rule.setMin("1");
				String error = m.group(4);
				if(error == null){
					error = "不能为空.";
				}
				rule.setError(error);
				addRule(rule);
				
			}
			//预定义格式
			else{
				m = Pattern.compile("^(\\w+)(:(\\w+)?)?(\\{(.+)\\})?$").matcher(expr);
				if(m.find()){
					String name = m.group(1);
					String error = m.group(5);
					
					String regex = RegExps.getRegExp(name);
					if(regex != null){
						RegexRule rule = new RegexRule();
						rule.setRuleArgs(m.group(3));
						rule.setCompare("or");
						rule.setRegexp(regex);
						if(error == null){
							error = RegExps.getRegExpErrorMsg(name);
							if(error == null){
								error = "输入格式错误.";
							}
						}
						rule.setError(error);
						addRule(rule);
					}
				}
			}
			
		}//for
		
	}
	
}
